package com.cyy.common.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cyy.common.constant.MenuType;
import com.cyy.common.exception.ProcessException;
import com.cyy.common.mapper.MenuMapper;
import com.cyy.common.pojo.dto.MenuFormDto;
import com.cyy.common.pojo.dto.MenuOptionDto;
import com.cyy.common.pojo.dto.MenuTreeDto;
import com.cyy.common.pojo.entity.Menu;
import com.cyy.common.pojo.query.system.SystemMenuQuery;
import com.cyy.common.service.MenuService;
import com.cyy.common.utils.TreeUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author 曹云友
 * @since 2024-03-29
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Override
    public List<MenuTreeDto> treeMenus(SystemMenuQuery query) {
        String keywords = query.getKeywords();
        List<Menu> menus = list(Wrappers.<Menu>lambdaQuery()
                .like(StringUtils.isNoneBlank(keywords), Menu::getMenuName, keywords)
                .orderByDesc(Menu::getMenuSort)
        );
        if (CollectionUtil.isEmpty(menus)) {
            throw new ProcessException("未找到对应菜单");
        }
        List<MenuTreeDto> menuTreeDtos = menus.stream().map(item -> {
            MenuTreeDto dto = new MenuTreeDto();
            dto.setId(item.getId());
            dto.setParentId(item.getParentId());
            dto.setName(item.getMenuName());
            dto.setType(MenuType.fromStr(item.getMenuType()));
            dto.setPath(item.getPath());
            dto.setComponent(item.getComponent());
            dto.setSort(item.getMenuSort());
            dto.setVisible(BooleanUtils.toBoolean(item.getStatus()));
            dto.setIcon(item.getIcon());
            dto.setRedirect(item.getRedirect());
            dto.setPerm(item.getPerms());
            return dto;
        }).collect(Collectors.toList());

        MenuTreeDto preNode = new MenuTreeDto();
        preNode.setId(0);
        HashSet<Integer> visited = new HashSet<>();
        TreeUtils.generatorTree(menuTreeDtos, preNode, visited);

        // 清理
        visited.clear();
        menuTreeDtos.clear();

        return preNode.getChildren();
    }

    @Override
    public List<MenuOptionDto> getMenuOptions() {

        List<Menu> menus = list(Wrappers.<Menu>lambdaQuery()
                .select(Menu::getId, Menu::getParentId, Menu::getMenuName)
                .eq(Menu::getStatus, Boolean.TRUE));
        if (CollectionUtil.isEmpty(menus)) {
            throw new ProcessException("未找到对应菜单");
        }
        List<MenuOptionDto> optionDtos = menus.stream().map(item -> {
            MenuOptionDto dto = new MenuOptionDto();
            dto.setId(item.getId());
            dto.setParentId(item.getParentId());
            dto.setName(item.getMenuName());
            return dto;
        }).collect(Collectors.toList());

        MenuOptionDto preNode = new MenuOptionDto();
        preNode.setId(0);
        HashSet<Integer> visited = new HashSet<>();
        TreeUtils.generatorTree(optionDtos, preNode, visited);

        visited.clear();
        optionDtos.clear();

        return preNode.getChildren();
    }

    @Override
    public MenuFormDto getFormItemById(Integer id) {
        Menu byId = getById(id);
        MenuFormDto dto = new MenuFormDto();
        dto.setId(byId.getId());
        dto.setParentId(byId.getParentId());
        dto.setName(byId.getMenuName());
        dto.setType(MenuType.fromStr(byId.getMenuType()));
        dto.setPath(byId.getPath());
        dto.setComponent(byId.getComponent());
        dto.setPerm(byId.getPerms());
        dto.setVisible(BooleanUtils.toBoolean(byId.getStatus()));
        dto.setSort(byId.getMenuSort());
        dto.setIcon(byId.getIcon());
        dto.setRedirect(byId.getRedirect());
        dto.setKeepAlive(byId.getKeepAlive());
        dto.setAlwaysShow(byId.getAlwaysShow());

        return dto;
    }

    @Override
    public void editMenu(MenuFormDto req) {
        Menu byId = getById(req.getId());
        byId.setParentId(req.getParentId());
        byId.setMenuName(req.getName());
        byId.setStatus(BooleanUtils.toInteger(req.getVisible()));
        byId.setIcon(req.getIcon());
        byId.setMenuSort(req.getSort());
        byId.setComponent(req.getComponent());
        byId.setPath(req.getPath());
        byId.setRedirect(req.getRedirect());
        byId.setMenuType(req.getType().name());
        byId.setPerms(req.getPerm());
        byId.setKeepAlive(req.getKeepAlive());
        byId.setAlwaysShow(req.getAlwaysShow());
        // 更新
        updateById(byId);
    }

    @Override
    public void deleteMenu(Integer id) {
        update(Wrappers.<Menu>lambdaUpdate().set(Menu::getStatus, Boolean.FALSE).eq(Menu::getId, id));
    }

    @Override
    public void addMenu(MenuFormDto req) {
        Menu menu = new Menu();

        menu.setParentId(req.getParentId());
        menu.setMenuName(req.getName());
        menu.setMenuType(req.getType().name());
        menu.setPath(req.getPath());
        menu.setComponent(MenuType.getComponentByType(req.getComponent(), req.getType()));
        menu.setPerms(req.getPerm());
        menu.setStatus(BooleanUtils.toInteger(req.getVisible()));
        menu.setMenuSort(req.getSort());
        menu.setIcon(req.getIcon());
        menu.setRedirect(req.getRedirect());
        menu.setKeepAlive(req.getKeepAlive());
        menu.setAlwaysShow(req.getAlwaysShow());

        save(menu);
    }
}
